// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>
using namespace std;

#include "Symbole.h"

/*! \file Abre.h
   \brief Les spécifications de tous les noeuds nécessaires pour faire un arbre
    Ce fichier contient les spécifications des classes Noeud, NoeudSeqInst,
    NoeudAffectation, NoeudInstSi, NoeudInstTq, NoeudInstRepeter, NoeudInstPour,
    NoeudInstEcrire, NoeudInstLire, NoeudOperateurBinaire
    \author Francis Guérin et Quentin Ansade
    \date 18.12.2013
 */

////////////////////////////////////////////////////////////////////////////////
class Noeud {
// classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait
// Remarque : la classe ne contient aucun constructeur
  public:
    virtual int  getValeur() =0 ; // méthode pure (non implémentée) qui rend la classe abstraite
    virtual void afficher(unsigned short indentation=0) { cout << setw(4*indentation) << " "; }
      // pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre

    virtual ~Noeud() {} // présence d'un destructeur virtuel conseillé dans les classes abstraites
};

////////////////////////////////////////////////////////////////////////////////
class NoeudSeqInst : public Noeud {
// classe pour représenter un noeud "sequence d'instruction"
// qui a autant de fils que d'instructions dans la séquence
  public:
     NoeudSeqInst();   // construit une séquence d'instruction vide
    ~NoeudSeqInst() {} // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue chaque instruction de la séquence
    void afficher(unsigned short indentation=0); // affiche la séquence d'instructions
    void ajouteInstruction(Noeud* instruction);  // ajoute une instruction à la séquence

  private:
    vector<Noeud *> tabInst; // pour stocker les instructions de la séquence
};

/*! \class NoeudAffectation
   /brief La classe d'un noeud représentant une affectation.
 
    Cette classe représente une affectation sous la forme d'un objet de type
    NoeudAffectation. Elle contient 2 méthodes :
    \li getValeur
    \li afficher
 */

////////////////////////////////////////////////////////////////////////////////
class NoeudAffectation : public Noeud {
// classe pour représenter un noeud "affectation"
// composé de 2 fils : la variable et l'expression qu'on lui affecte
  public:
     /*! \fn NoeudAffectation(Noeud* variable, Noeud* expression)
         \brief Constructeur de la classe NoeudAffectation.
         Ce constructeur crée un Noeud Affectation à l'aide des deux attributs
         "variable" et "expression".
         \param variable - un pointeur sur un Noeud qui sera éventuellement changé
                            en pointeur sur un Symbole Valué
         \param expression - un pointeur sur un Noeud qui sera éventuellement changé
                              en Symbole Valué.
      */
     NoeudAffectation(Noeud* variable, Noeud* expression);
     
     /*! \fn ~NoeudAffectation()
         \brief Destructeur de la classe NoeudAffectation
         Doit être présent en raison du destructeur virtuel de la classe Noeud
      */
    ~NoeudAffectation() {}
    
    /*! \fn getValeur()
        \brief Fonction qui évalue l'expression et affecteur sa valeur à la variable
        Cette fonction évalue l'expression et affecte cette valeur à la variable en appelant
        en la fonction getValeur d'expression qui est un NoeudOperateurBinaire
        \return la valeur de l'expression
     */
    int getValeur();
    
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Fonction qui affiche un NoeudAffectation
        Cette fonction affiche un NoeudAffectation avec l'indentation appropriée
        à l'aide de la fonction afficher de Noeud.
        \param indentation - indentation à utiliser pour afficher le noeud et ses
                            sous-noeuds.
     */
    void afficher(unsigned short indentation=0); // affiche l'affectation

  private:
    /*! \var Noeud* variable
        \brief Pointeur sur un noeud (plus précisément un noeud SymboleValué)
     */
    Noeud* variable;
    /*! \var Noeud* expression
        \brief Pointeur sur un noeud (plus précisément un NoeudOperateurBinaire)
     */
    Noeud* expression;
};


////////////////////////////////////////////////////////////////////////////////
class NoeudInstSi : public Noeud {
// classe pour représenter un noeud "si"
//composé de l'expression booléenne, un pointeur sur une seqInst ainsi qu'un
//pointeur sur le prochain "sinon si"
    public:
        NoeudInstSi(Noeud* expbool, Noeud* seqInst, Noeud* sinon);      // construit une instruction si
        ~NoeudInstSi() {};  // à cause du destructeur virtuel de la classe Noeud
        int getValeur();    // évalue les instructions de la bonne séquence
        void afficher(unsigned short indentation=0);
        void ajouteSeqInst(Noeud* sequence);
        void ajouteSinon(Noeud* sinon);
        
    private:
        Noeud * expbool;
        Noeud * seqInst;
        Noeud * sinon;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstTq : public Noeud {
// classe pour représenter un noeud "tantque"
    public:
        NoeudInstTq(Noeud* expressBool, Noeud* seqInst);      // construit une instruction tant que
        ~NoeudInstTq() {};  // à cause du destructeur virtuel de la classe Noeud
        int getValeur();    // évalue les instructions de la boucle
        void afficher(unsigned short indentation=0);
        void ajouteSeqInst(Noeud* sequence);
        
    private:
        Noeud* expressBool;
        Noeud* tabSeqInst;
};
////////////////////////////////////////////////////////////////////////////////
class NoeudInstRepeter : public Noeud {
// classe pour représenter un noeud "tantque"
    public:
        NoeudInstRepeter(Noeud* expressBool, Noeud* seqInst);      // construit une instruction repeter
        ~NoeudInstRepeter() {};  // à cause du destructeur virtuel de la classe Noeud
        int getValeur();    // évalue les instructions de la boucle
        void afficher(unsigned short indentation=0);
        void ajouteSeqInst(Noeud* sequence);
        
    private:
        Noeud* expressBool;
        Noeud* tabSeqInst;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstPour : public Noeud {
//classe pour représenter un noeud "pour"

    public:
        NoeudInstPour(Noeud* initialisation = NULL, Noeud* condition = NULL,
                Noeud* operation = NULL, Noeud* seqInst = NULL );
        ~NoeudInstPour() {};
        int getValeur(); //évalue les instructions de la boucle
        void afficher(unsigned short indentation = 0);
        void setInitialisation(Noeud* initialisation);
        void setCondition(Noeud* condition);
        void setOperation(Noeud* operation);
        void setSeqInst(Noeud* seqInst);
        
    private:
        Noeud* initialisation;
        Noeud* condition;
        Noeud* operation;
        Noeud* seqInst;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstEcrire : public Noeud {
// classe pour représenter un noeud "ecrire"
    public:
        NoeudInstEcrire();
        ~NoeudInstEcrire() {};
        int getValeur(); //affiche à l'écran l'expression ou la chaîne
        void afficher(unsigned short indentation=0);
        void ajouteExpression(Noeud* expression);
        void ajouteChaine(string chaine);
        
    private:
        Noeud* expression;
        string chaine;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstLire : public Noeud {
// classe pour représenter un noeud "lire"
    
    public:
        NoeudInstLire(Noeud* variable = NULL);
        ~NoeudInstLire() {};
        int getValeur(); //Affecte la valeur lue au clavier à la variable
        void afficher(unsigned short indentation=0);
        void ajouteVariable(Noeud* variable);
        
    private:
        Noeud* variable;
    
};
////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurBinaire : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:
    NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit
   ~NoeudOperateurBinaire() {} // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation=0); // affiche l'opération

  private:
    Symbole operateur;
    Noeud*  operandeGauche;
    Noeud*  operandeDroit;
};

#endif /* ARBRE_H_ */
